package com.yixun.qfbao.api.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.beust.jcommander.internal.Lists;
import com.yixun.qfbao.api.service.DeptPermissionService;
import com.yixun.qfbao.api.service.RoleCaseMemberService;
import com.yixun.qfbao.apidto.AgencyPartnerPermission;
import com.yixun.qfbao.apidto.DeptPermissionBindDto;
import com.yixun.qfbao.apidto.RoleCaseMemberDto;
import com.yixun.qfbao.apidto.SetDeptPermissionReqDto;
import com.yixun.qfbao.constant.RedisKeyConstant;
import com.yixun.qfbao.dao.DepartmentDao;
import com.yixun.qfbao.dao.DeptPermissionDao;
import com.yixun.qfbao.mapper.ChannelRoleMapper;
import com.yixun.qfbao.mapper.CompanyMapper;
import com.yixun.qfbao.mapper.RoleCaseMemberMapper;
import com.yixun.qfbao.model.*;
import com.yixun.qfbao.model.dto.*;
import com.yixun.qfbao.model.enums.*;
import com.yixun.qfbao.service.PartnerInfoService;
import com.yixun.qfbao.util.RedisUtil;
import com.yixun.qfbao.xf.model.enums.DeptPermissionEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class DeptPermissionServiceImpl implements DeptPermissionService {

    @Autowired
    private DeptPermissionDao deptPermissionDao;
    @Autowired
    private PartnerInfoService partnerInfoService;
    @Autowired
    private RoleCaseMemberService roleCaseMemberService;
    @Autowired
    private DepartmentDao departmentDao;
    @Autowired
    private RoleCaseMemberMapper roleCaseMemberMapper;
    @Autowired
    private CompanyMapper companyMapper;
    @Autowired
    private ChannelRoleMapper channelRoleMapper;
    
    @Override
    public Map<String, String> getDPLevelByBelongsId(Long belongsId) {
        Map<String, String> dpMap = new HashMap<>();
        // 选中的权限类型
        dpMap.put(DPDescEnum.DP_TYPE.getNo(), DeptPermissionEnum.ALL.getNo());
        dpMap.put(DPDescEnum.EXISTS_PERSONAL.getNo(), PersonalPermissionEnum.NOT_EXISTS.getNo());
        Example example = new Example(DeptPermission.class);
        example.createCriteria().andEqualTo("belongsId", belongsId)
                .andEqualTo("delFlag", DelFlagEnum.UNDEL.getNo());
        List<DeptPermission> deptPermissions = deptPermissionDao.selectListByExample(example);
        if (CollectionUtils.isNotEmpty(deptPermissions)) {
            dpMap.put(DPDescEnum.EXISTS_PERSONAL.getNo(), PersonalPermissionEnum.EXISTS.getNo());
            DeptPermission deptPermission = deptPermissions.get(0);
            dpMap.put(DPDescEnum.DP_TYPE.getNo(), deptPermission.getDeptPermission());
        }
        return dpMap;
    }

    @Override
    public DeptPermissionBindDto getBindDeptPermission(DeptPermissionDto entity) {
        DeptPermissionBindDto dto = new DeptPermissionBindDto();
        Map<String, String> dpMap = getDPLevelByBelongsId(entity.getBelongsId());
        String existsPersonal = dpMap.get(DPDescEnum.EXISTS_PERSONAL.getNo());
        if(PersonalPermissionEnum.NOT_EXISTS.getNo().equals(existsPersonal)){
            // 不存在记录,直接使用角色权限的设置
            PartnerInfo partnerInfo = partnerInfoService.selectById(entity.getBelongsId());
            RoleCaseMemberDto roleCaseMemberDto = roleCaseMemberService.listRoleCaseMember(partnerInfo.getUserRoleId(), partnerInfo.getHigherid());
            dto.setDeptPermission(roleCaseMemberDto.getDeptPermission());
            dto.setNodeList(roleCaseMemberDto.getRoleCaseMembers());
        }else{
            dto.setDeptPermission(dpMap.get(DPDescEnum.DP_TYPE.getNo()));
            List<Node> result = Lists.newArrayList();
            List<Node> nodes = deptPermissionDao.getBindNodes(entity);
            if (CollectionUtils.isNotEmpty(nodes)) {
                for (Node node : nodes) {
                    //顶级部门
                    if (node.getpId().equals("0")) {
                        node.setOther(node.getName());
                        if (StringUtils.isNotBlank(node.getrId())) {
                            node.setSelected(true);
                        } else {
                            node.setSelected(false);
                        }
                        result.add(node);
                    }
                    for (Node node1 : nodes) {
                        if (node1.getpId().equals(node.getId())) {
                            if (node.getChildren() == null) {
                                node.setChildren(Lists.newArrayList());
                            }
                            node1.setOther(node.getOther() + ";" + node1.getName());
                            if (StringUtils.isNotBlank(node1.getrId())) {
                                node1.setSelected(true);
                            } else {
                                node1.setSelected(false);
                            }
                            node.getChildren().add(node1);
                        }
                    }
                }
                dto.setNodeList(result);
            }
        }
        return dto;
    }

    @Override
    public void setDeptPermission(SetDeptPermissionReqDto reqDto) {
        // 清除用户原绑定的数据
        if (Objects.nonNull(reqDto.getBelongsId())) {
            DeptPermissionDto dpDto = new DeptPermissionDto();
            dpDto.setBelongs(BelongsEnum.PERSONAL.getNo());
            dpDto.setBelongsId(reqDto.getBelongsId());
            List<DeptPermission> dpList = deptPermissionDao.selectListByDto(dpDto);
            List<Long> dpIds = dpList.stream().map(DeptPermission::getId).collect(Collectors.toList());
            DeptPermission dp = new DeptPermission();
            dp.setDelFlag(DelFlagEnum.DEL.getNo());
            deptPermissionDao.updateByIds(dp, dpIds);
        }

        if (Objects.nonNull(reqDto.getBindDto())) {
            DeptPermissionBindDto bindDto = reqDto.getBindDto();
            List<DeptPermission> deptPermissions = Lists.newArrayList();
            if (StringUtils.equals(DeptPermissionEnum.NOT.getNo(), bindDto.getDeptPermission())) {
                List<String> selectedOrgs = bindDto.getSelected();
                if (CollectionUtils.isNotEmpty(selectedOrgs)) {
                    DeptPermission deptPermission = new DeptPermission();
                    if (selectedOrgs.size() == 1 && "ALL".equals(selectedOrgs.get(0))) {
                        deptPermission.setBelongs(BelongsEnum.PERSONAL.getNo());
                        deptPermission.setBelongsId(reqDto.getBelongsId());
                        deptPermission.setCompanyId(reqDto.getMerchantId());
                        deptPermission.setDeptPermission(DeptPermissionEnum.NOT.getNo());
                        deptPermission.setDeptId(0L);
                        deptPermission.setCreateUserId(Long.valueOf(reqDto.getUserId()));
                        deptPermission.setCreateTime(Calendar.getInstance().getTime());
                        deptPermission.setDelFlag(DelFlagEnum.UNDEL.getNo());
                        deptPermissions.add(deptPermission);
                    } else {
                        for (String deptId : selectedOrgs) {
                            deptPermission = new DeptPermission();
                            deptPermission.setBelongs(BelongsEnum.PERSONAL.getNo());
                            deptPermission.setBelongsId(reqDto.getBelongsId());
                            deptPermission.setCompanyId(reqDto.getMerchantId());
                            deptPermission.setDeptPermission(DeptPermissionEnum.NOT.getNo());
                            deptPermission.setDeptId(Long.parseLong(deptId));
                            deptPermission.setCreateUserId(Long.valueOf(reqDto.getUserId()));
                            deptPermission.setCreateTime(Calendar.getInstance().getTime());
                            deptPermission.setDelFlag(DelFlagEnum.UNDEL.getNo());
                            deptPermissions.add(deptPermission);
                        }
                    }
                }
            } else {
                DeptPermission deptPermission = new DeptPermission();
                deptPermission.setBelongs(BelongsEnum.PERSONAL.getNo());
                deptPermission.setBelongsId(reqDto.getBelongsId());
                deptPermission.setCompanyId(reqDto.getMerchantId());
                deptPermission.setDeptPermission(bindDto.getDeptPermission());
                deptPermission.setCreateUserId(Long.valueOf(reqDto.getUserId()));
                deptPermission.setCreateTime(Calendar.getInstance().getTime());
                deptPermission.setDelFlag(DelFlagEnum.UNDEL.getNo());
                deptPermissions.add(deptPermission);
            }
            if (CollectionUtils.isNotEmpty(deptPermissions)) {
                deptPermissionDao.createList(deptPermissions);
            }
        }
    }

    @Override
    public void setAgencyDeptPermission(SetDeptPermissionReqDto reqDto) {
        // 清除用户原绑定的数据
        if (Objects.nonNull(reqDto.getBelongsId())) {
            DeptPermissionDto dpDto = new DeptPermissionDto();
            dpDto.setBelongs(BelongsEnum.ROLE.getNo());
            dpDto.setBelongsId(reqDto.getBelongsId());
            List<DeptPermission> dpList = deptPermissionDao.selectListByDto(dpDto);
            List<Long> dpIds = dpList.stream().map(DeptPermission::getId).collect(Collectors.toList());
            DeptPermission dp = new DeptPermission();
            dp.setDelFlag(DelFlagEnum.DEL.getNo());
            deptPermissionDao.updateByIds(dp, dpIds);
        }
        DeptPermission deptPermission = new DeptPermission();
        deptPermission.setBelongs(BelongsEnum.ROLE.getNo());
        deptPermission.setBelongsId(reqDto.getBelongsId());
        deptPermission.setCompanyId(reqDto.getMerchantId());
        deptPermission.setDeptPermission(reqDto.getBindDto().getDeptPermission());
        deptPermission.setDeptId(null);
        deptPermission.setCreateUserId(Long.valueOf(reqDto.getUserId()));
        deptPermission.setCreateTime(Calendar.getInstance().getTime());
        deptPermission.setDelFlag(DelFlagEnum.UNDEL.getNo());
        deptPermissionDao.create(deptPermission);
    }

    @Override
    public void resetDeptPermission(Long belongsId) {
        // 清除用户机构权限,即还原成角色权限
        if (Objects.nonNull(belongsId)) {
            DeptPermissionDto dpDto = new DeptPermissionDto();
            dpDto.setBelongsId(belongsId);
            List<DeptPermission> dpList = deptPermissionDao.selectListByDto(dpDto);
            List<Long> dpIds = dpList.stream().map(DeptPermission::getId).collect(Collectors.toList());
            DeptPermission dp = new DeptPermission();
            dp.setDelFlag(DelFlagEnum.DEL.getNo());
            deptPermissionDao.updateByIds(dp, dpIds);

            // 清除此用户的楼盘权限
            String redisKey = RedisKeyConstant.Permission.DEV_USER_ORG_PERMISSION + belongsId;
            RedisUtil.delete(redisKey);
        }
    }

    /**
     * @param partnerId
     * @return
     */
    @Override
    public List<Long> getPartnerDeptPermission(Long partnerId) {
        long begin = System.currentTimeMillis();
        List<Long> permissionDeptIds = new ArrayList<>();
        PartnerInfo partnerInfo = partnerInfoService.selectById(partnerId);
        if (Objects.isNull(partnerInfo) || MechanismAccountTypeEnum.mechanism.getNo().equals(partnerInfo.getAccountType())) {
            return permissionDeptIds;
        }
        String devUserCompanyPermission = RedisKeyConstant.Permission.DEV_USER_ORG_PERMISSION + partnerId;
        String devRoleCompanyPermission = RedisKeyConstant.Permission.DEV_ROLE_ORG_PERMISSION + partnerInfo.getUserRoleId();

        // 1、查看客户是否拥有个人权限
        Example example = new Example(DeptPermission.class);
        example.createCriteria().andEqualTo("belongsId", partnerId)
                .andEqualTo("delFlag", DelFlagEnum.UNDEL.getNo());
        List<DeptPermission> dpList = deptPermissionDao.selectListByExample(example);
        log.info("deptPermissionService --> getPartnerDeptPermission --> partnerId: {}, dpList: {}", partnerId, dpList.size());
        // 判断用户是否个人权限.存在个人权限配置就以个人权限为准
        if (CollectionUtils.isNotEmpty(dpList)) {
        	if(RedisUtil.hasKey(devUserCompanyPermission)){
                Object object = RedisUtil.get(devUserCompanyPermission);
                if(Objects.nonNull(object)){
                    permissionDeptIds = (List<Long>)object;
                    return permissionDeptIds;
                }
            }
            // 个人权限
            Map<String, String> dpMap = getDPLevelByBelongsId(partnerId);
            String dpType = dpMap.get(DPDescEnum.DP_TYPE.getNo());
            log.info("deptPermissionService --> getPartnerDeptPermission --> partnerId: {}, personal dpMap: {}", partnerId, dpMap);
            // 本部权限为全部或机构是全选操作.可看所有部门.无需设置部门查看范围
            if (StringUtils.equals(DeptPermissionEnum.ALL.getNo(), dpType)) {
            } else if (StringUtils.equals(DeptPermissionEnum.NOT.getNo(), dpType)) {
                // 不适用部门权限时,使用机构勾选权限.
                // 其中包含全部和勾选机构权限.全部以在if条件中过滤.
                // 此处只剩下主动勾选的部门
                permissionDeptIds = dpList.stream().map(DeptPermission::getDeptId).collect(Collectors.toList());
            } else if (StringUtils.equals(DeptPermissionEnum.DEPT.getNo(), dpType)) {
                // 本部范围
                // 获取当前用户部门及其所有子部门
                List<Department> departments = departmentDao.listDeptByParentId(partnerInfo.getHigherid(), partnerInfo.getDeptId());
                if (CollectionUtils.isNotEmpty(departments)) {
                    // 部门集合
                    List<Long> deptIds = departments.stream().map(Department::getId).collect(Collectors.toList());
                    // 部门下的所有用户(未删除且状态有效的客户)
                    List<PartnerInfoDto> infos = partnerInfoService.listPartnerInfoByDeptIds(deptIds);
                    permissionDeptIds = filterPartnerPermissionByDept(infos);
                }
            }
            log.info("deptPermissionService --> getPartnerDeptPermission --> partnerId: {}, personal permissionDeptIds: {}", partnerId, permissionDeptIds);
        } else {
            if(RedisUtil.hasKey(devRoleCompanyPermission)){
                Object object = RedisUtil.get(devRoleCompanyPermission);
                if(Objects.nonNull(object)){
                    permissionDeptIds = (List<Long>)object;
                    return permissionDeptIds;
                }
            }
            // 角色权限
            Map<String, String> dpMap = roleCaseMemberService.getDeptPermissionByRoleId(partnerInfo.getUserRoleId());
            //部门权限0不使用1全部2本部3本人
            String dpType = StringUtils.defaultIfBlank(dpMap.get(DPDescEnum.DP_TYPE.getNo()), DeptPermissionEnum.ALL.getNo());
            log.info("deptPermissionService --> getPartnerDeptPermission --> partnerId: {}, role dpMap: {}", partnerId, dpMap);
            if (StringUtils.equals(DeptPermissionEnum.ALL.getNo(), dpType)) {
            } else if (StringUtils.equals(DeptPermissionEnum.NOT.getNo(), dpType)) {
                // 不适用部门权限时,使用机构勾选权限.
                // 其中包含全部和勾选机构权限.全部以在if条件中过滤.
                // 此处只剩下主动勾选的部门
                permissionDeptIds = roleCaseMemberService.listDeptByRoleId(partnerInfo.getUserRoleId());
            } else if (StringUtils.equals(DeptPermissionEnum.DEPT.getNo(), dpType)) {
                // 本部范围
                // 获取当前用户部门及其所有子部门
                List<Department> departments = departmentDao.listDeptByParentId(partnerInfo.getHigherid(), partnerInfo.getDeptId());
                if (CollectionUtils.isNotEmpty(departments)) {
                    // 部门集合
                    List<Long> deptIds = departments.stream().map(Department::getId).collect(Collectors.toList());
                    // 部门下的所有用户(未删除且状态有效的客户)
                    List<PartnerInfoDto> infos = partnerInfoService.listPartnerInfoByDeptIds(deptIds);
                    permissionDeptIds = filterPartnerPermissionByDept(infos);
                }
            }
            log.info("deptPermissionService --> getPartnerDeptPermission --> partnerId: {}, role permissionDeptIds: {}", partnerId, permissionDeptIds);
        }
        // 筛选子部门
        permissionDeptIds = filterChildDept(permissionDeptIds);

        if (CollectionUtils.isNotEmpty(dpList)) {
            RedisUtil.set(devUserCompanyPermission, permissionDeptIds);
            RedisUtil.expire(devUserCompanyPermission, 3, TimeUnit.DAYS);
        }else{
            RedisUtil.set(devRoleCompanyPermission, permissionDeptIds);
            RedisUtil.expire(devUserCompanyPermission, 3, TimeUnit.DAYS);
        }
        long end = System.currentTimeMillis();
        log.info("deptPermissionService --> getPartnerDeptPermission --> 公司: {}, 人员: {}, 角色: {}, 耗时: {}", partnerInfo.getHigherid(), partnerInfo.getId(), partnerInfo.getUserRoleId() , end - begin);
        return permissionDeptIds;
    }

    @Override
    public List<Long> getPartnerDeptPermissionForWx(Long partnerId) {
        long begin = System.currentTimeMillis();
        List<Long> permissionDeptIds = new ArrayList<>();
        PartnerInfo partnerInfo = partnerInfoService.selectById(partnerId);
        if (Objects.isNull(partnerInfo) || MechanismAccountTypeEnum.mechanism.getNo().equals(partnerInfo.getAccountType())) {
            return permissionDeptIds;
        }
        // 1、查看客户是否拥有个人权限
        Example example = new Example(DeptPermission.class);
        example.createCriteria().andEqualTo("belongsId", partnerId)
                .andEqualTo("delFlag", DelFlagEnum.UNDEL.getNo());
        List<DeptPermission> dpList = deptPermissionDao.selectListByExample(example);
        log.info("deptPermissionService --> getPartnerDeptPermission --> partnerId: {}, dpList: {}", partnerId, dpList.size());
        // 判断用户是否个人权限.存在个人权限配置就以个人权限为准
        if (CollectionUtils.isNotEmpty(dpList)) {
            // 个人权限
            Map<String, String> dpMap = getDPLevelByBelongsId(partnerId);
            String dpType = dpMap.get(DPDescEnum.DP_TYPE.getNo());
            log.info("deptPermissionService --> getPartnerDeptPermission --> partnerId: {}, personal dpMap: {}", partnerId, dpMap);
            // 本部权限为全部或机构是全选操作.可看所有部门.无需设置部门查看范围
            if (StringUtils.equals(DeptPermissionEnum.ALL.getNo(), dpType)) {
            } else if (StringUtils.equals(DeptPermissionEnum.NOT.getNo(), dpType)) {
                // 不适用部门权限时,使用机构勾选权限.
                // 其中包含全部和勾选机构权限.全部以在if条件中过滤.
                // 此处只剩下主动勾选的部门
                permissionDeptIds = dpList.stream().map(DeptPermission::getDeptId).collect(Collectors.toList());
            } else if (StringUtils.equals(DeptPermissionEnum.DEPT.getNo(), dpType)) {
                // 本部范围
                // 获取当前用户部门及其所有子部门
                List<Department> departments = departmentDao.listDeptByParentId(partnerInfo.getHigherid(), partnerInfo.getDeptId());
                if (CollectionUtils.isNotEmpty(departments)) {
                    // 部门集合
                    List<Long> deptIds = departments.stream().map(Department::getId).collect(Collectors.toList());
                    // 部门下的所有用户(未删除且状态有效的客户)
                    List<PartnerInfoDto> infos = partnerInfoService.listPartnerInfoByDeptIds(deptIds);
                    permissionDeptIds = filterPartnerPermissionByDept(infos);
                }
            }
            log.info("deptPermissionService --> getPartnerDeptPermission --> partnerId: {}, personal permissionDeptIds: {}", partnerId, permissionDeptIds);
        } else {
            // 角色权限
            Map<String, String> dpMap = roleCaseMemberService.getDeptPermissionByRoleId(partnerInfo.getUserRoleId());
            //部门权限0不使用1全部2本部3本人
            String dpType = StringUtils.defaultIfBlank(dpMap.get(DPDescEnum.DP_TYPE.getNo()), DeptPermissionEnum.ALL.getNo());
            log.info("deptPermissionService --> getPartnerDeptPermission --> partnerId: {}, role dpMap: {}", partnerId, dpMap);
            if (StringUtils.equals(DeptPermissionEnum.ALL.getNo(), dpType)) {
            } else if (StringUtils.equals(DeptPermissionEnum.NOT.getNo(), dpType)) {
                // 不适用部门权限时,使用机构勾选权限.
                // 其中包含全部和勾选机构权限.全部以在if条件中过滤.
                // 此处只剩下主动勾选的部门
                permissionDeptIds = roleCaseMemberService.listDeptByRoleId(partnerInfo.getUserRoleId());
            } else if (StringUtils.equals(DeptPermissionEnum.DEPT.getNo(), dpType)) {
                // 本部范围
                // 获取当前用户部门及其所有子部门
                List<Department> departments = departmentDao.listDeptByParentId(partnerInfo.getHigherid(), partnerInfo.getDeptId());
                if (CollectionUtils.isNotEmpty(departments)) {
                    // 部门集合
                    List<Long> deptIds = departments.stream().map(Department::getId).collect(Collectors.toList());
                    // 部门下的所有用户(未删除且状态有效的客户)
                    List<PartnerInfoDto> infos = partnerInfoService.listPartnerInfoByDeptIds(deptIds);
                    permissionDeptIds = filterPartnerPermissionByDept(infos);
                }
            }
            log.info("deptPermissionService --> getPartnerDeptPermission --> partnerId: {}, role permissionDeptIds: {}", partnerId, permissionDeptIds);
        }
        // 筛选子部门
        permissionDeptIds = filterChildDept(permissionDeptIds);

        long end = System.currentTimeMillis();
        log.info("deptPermissionService --> getPartnerDeptPermission --> 公司: {}, 人员: {}, 角色: {}, 耗时: {}", partnerInfo.getHigherid(), partnerInfo.getId(), partnerInfo.getUserRoleId() , end - begin);
        return permissionDeptIds;
    }

    /**
     * 筛选出公司级别的部门
     *
     * @param permissionDeptIds
     * @return
     */
    public List<Long> filterChildDept(List<Long> permissionDeptIds) {
        if (CollectionUtils.isEmpty(permissionDeptIds)) {
            return permissionDeptIds;
        }
        DepartmentDto deptDto = new DepartmentDto();
        deptDto.setDeptIds(permissionDeptIds);
        List<Department> deptList = departmentDao.selectListByDto(deptDto);
        if (CollectionUtils.isEmpty(deptList)) {
            return permissionDeptIds;
        }
        List<String> permissionCodes = deptList.stream()
                .map(Department::getPermissionCode)
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(permissionCodes)) {
            return permissionDeptIds;
        }
        deptDto = new DepartmentDto();
        deptDto.setPermissionCodes(permissionCodes);
        deptList = departmentDao.selectListByPermissionCodes(deptDto);
        return deptList.stream().map(Department::getId).collect(Collectors.toList());
    }


    /**
     * 本部权限,获取所有用户相关的权限集合
     * 1、先过滤拥有个人权限的用户,当存在全部权限时,直接跳出并给予全部权限
     * 2、再过滤无个人权限的用户,使用角色权限去获取相关角色权限,当存在全部,直接授予全部
     * 3、当个人和全部都无全部时,合并两个集合获取到的部门权限
     * @param partnerInfoList
     * @return
     */
    public List<Long> filterPartnerPermissionByDept(List<PartnerInfoDto> partnerInfoList){
        List<Long> permissionDeptIds = new ArrayList<>();
        // 用户的所有角色集合
        List<Long> partnerIds = partnerInfoList.stream().map(PartnerInfoDto::getId).collect(Collectors.toList());
        log.info("deptPermissionService --> filterPartnerPermissionByDept --> personal partnerIds: {}", partnerIds);
        // 所有角色对应的权限交集
        if (CollectionUtils.isNotEmpty(partnerIds)) {
            Example example = new Example(DeptPermission.class);
            example = new Example(DeptPermission.class);
            example.createCriteria()
                    .andEqualTo("delFlag", DelFlagEnum.UNDEL.getNo())
                    .andIn("belongsId", partnerIds);
            List<DeptPermission> deptPermissionList = deptPermissionDao.selectListByExample(example);
            if (CollectionUtils.isNotEmpty(deptPermissionList)) {
                boolean flag = deptPermissionList.stream().anyMatch(item ->
                    DeptPermissionEnum.ALL.getNo().equals(item.getDeptPermission())
                );
                if (!flag) {
                    // 存在个人权限的用户
                    Set<Long> existsIds = new HashSet<>();
                    for (DeptPermission deptPermission : deptPermissionList) {
                        existsIds.add(deptPermission.getBelongsId());
                        if (DeptPermissionEnum.NOT.getNo().equals(deptPermission.getDeptPermission())) {
                            permissionDeptIds.add(deptPermission.getDeptId());
                        }
                    }
                    List<Long> notExistIds = new ArrayList<>();
                    for(Long existsId: partnerIds){
                        if(!existsIds.contains(existsId)){
                            notExistIds.add(existsId);
                        }
                    }
                    // 不为空,再次判断无个人权限的用户角色权限集合
                    if(CollectionUtils.isNotEmpty(notExistIds)){
                        PartnerInfoDto piDto = new PartnerInfoDto();
                        piDto.setIds(notExistIds);
                        List<PartnerInfo> notExistsPartners = partnerInfoService.selectListByDto(piDto);
                        // 用户的所有角色集合
                        List<Long> roleIds = notExistsPartners.stream().map(PartnerInfo::getUserRoleId).collect(Collectors.toList());
                        log.info("deptPermissionService --> filterPartnerPermissionByDept --> personal roleIds: {}", roleIds);
                        // 所有角色对应的权限交集
                        List<Long> rolePermissionDeptIds = roleCaseMemberService.listDeptByRoleIds(roleIds);
                        if(CollectionUtils.isNotEmpty(rolePermissionDeptIds)){
                            permissionDeptIds.addAll(rolePermissionDeptIds);
                        }else {
                            permissionDeptIds = rolePermissionDeptIds;
                        }
                    }
                }
            }else {
                // 用户的所有角色集合
                List<Long> roleIds = partnerInfoList.stream().map(PartnerInfo::getUserRoleId).collect(Collectors.toList());
                // 所有角色对应的权限交集
                List<Long> rolePermissionDeptIds = roleCaseMemberService.listDeptByRoleIds(roleIds);
                if(CollectionUtils.isNotEmpty(rolePermissionDeptIds)){
                    permissionDeptIds.addAll(rolePermissionDeptIds);
                }else {
                    permissionDeptIds = rolePermissionDeptIds;
                }
            }
        }
        return permissionDeptIds;
    }
    
    /**
     * 添加个人的部门权限  add by zilong.liu
     */
	@Override
	public void addPersonalDeptPermission(Long partnerId, Long roleId, Long companyId, Long deptId) {
		// 如果是分销机构进行的新增，则直接刷新权限即可。
		if(Objects.isNull(roleId)){
		    return;
        }
		
		log.info("DeptPermissionServiceImpl-》addPersonalDeptPermission—》， "
				+ "当前入参为partnerId:{}, roleId:{}, companyId:{}, deptId:{}", partnerId, roleId, companyId, deptId);
		// 获取当前所使用的权限类型。
		DeptPermissionDto entity = new DeptPermissionDto();
		entity.setBelongsId(partnerId);
		entity.setDelFlag(DelFlagEnum.UNDEL.getNo());
		List<DeptPermission> deptPermissions = deptPermissionDao.selectListByDto(entity);
		log.info("DeptPermissionServiceImpl-》addPersonalDeptPermission—》， 当前人员获取到的个人机构deptPermissions为:{}", 
				JSONObject.toJSONString(deptPermissions));
		// 管理员直接清空权限即可
		if(CollectionUtils.isNotEmpty(deptPermissions)) {
			// 1、 使用的是全部、本部（本部概念被移除），则不进行处理。。
			DeptPermission deptPermission = deptPermissions.get(0);
			if(DeptPermissionEnum.NOT.getNo().equals(deptPermission.getDeptPermission()) 
					|| DeptPermissionEnum.MYSELF.getNo().equals(deptPermission.getDeptPermission())) {
				// 新增部门权限数据
				deptPermission.setCreateTime(new Date());
				deptPermission.setUpdateTime(new Date());
				deptPermission.setDeptId(deptId);
				log.info("DeptPermissionServiceImpl-》addPersonalDeptPermission—》, 本次新增数据为:{}", 
						JSONObject.toJSONString(deptPermission));
				deptPermissionDao.create(deptPermission);
			}
		}else {
			// ------------------------ 这是一个分界线下述处理角色的权限信息 -----------------------------------------
			// 如果角色勾选的是全部或者本部，则不处理
			// 如果角色机构权限为个人，则把当前角色的数据刷至当前人员，并且当前人员新增此部门权限，并且不需要处理当前个人redis的问题
			// 如果deptPermissions没有，则使用的是角色权限
			List<RoleCaseMember> roleCaseMembers = roleCaseMemberMapper.listRoleCaseMember(roleId);
			log.info("DeptPermissionServiceImpl-》addPersonalDeptPermission—》, 本次获取的角色权限列表为:{}", 
					JSONObject.toJSONString(roleCaseMembers));
			// 角色权限为空，则代表是全部，则不需要进行处理
			// 1、只处理角色权限为个人的情况
			if(CollectionUtils.isNotEmpty(roleCaseMembers) && (DeptPermissionEnum.MYSELF.getNo().equals(roleCaseMembers.get(0).getDeptPermission())
					|| DeptPermissionEnum.NOT.getNo().equals(roleCaseMembers.get(0).getDeptPermission()))) {
				List<DeptPermission> roleDeptPermissions = Lists.newArrayList();
				roleCaseMembers.stream().forEach(roleCaseMember -> {
					DeptPermission deptPermission = new DeptPermission();
					deptPermission = new DeptPermission();
	                deptPermission.setBelongs(BelongsEnum.PERSONAL.getNo());
	                deptPermission.setBelongsId(partnerId);
	                deptPermission.setCompanyId(roleCaseMember.getMerchantId());
	                deptPermission.setDeptPermission(DeptPermissionEnum.NOT.getNo());
	                deptPermission.setDeptId(roleCaseMember.getDeptId());
	                deptPermission.setCreateUserId(partnerId);
	                deptPermission.setCreateTime(Calendar.getInstance().getTime());
	                deptPermission.setDelFlag(DelFlagEnum.UNDEL.getNo());
	                roleDeptPermissions.add(deptPermission);
				});
				// 2、新增当前数据
				DeptPermission deptPermission = new DeptPermission();
				deptPermission = new DeptPermission();
		        deptPermission.setBelongs(BelongsEnum.PERSONAL.getNo());
		        deptPermission.setBelongsId(partnerId);
		        deptPermission.setCompanyId(companyId);
		        deptPermission.setDeptPermission(DeptPermissionEnum.NOT.getNo());
		        deptPermission.setDeptId(deptId);
		        deptPermission.setCreateUserId(partnerId);
		        deptPermission.setCreateTime(Calendar.getInstance().getTime());
		        deptPermission.setDelFlag(DelFlagEnum.UNDEL.getNo());
		        roleDeptPermissions.add(deptPermission);
		        log.info("DeptPermissionServiceImpl-》addPersonalDeptPermission—》, 本次插入的个人权限列表为:{}", 
						JSONObject.toJSONString(roleDeptPermissions));
		        // 3、 插入
		        deptPermissionDao.createList(roleDeptPermissions);
			}
		}
		cleanCompanyCacheByPartner(partnerId);
	}
	
	/**
	 * 根据当前人员，清除公司所有人员和角色的机构权限
	 */
	@Override
	public void cleanCompanyCacheByCompanyUuid(String companyUuid){
		if(Objects.isNull(companyUuid)){
			return;
		}
		CompanyDto companyDto = new CompanyDto();
		companyDto.setCompanyUuid(companyUuid);
		companyDto.setDelFlag(DelFlagEnum.UNDEL.getNo());
		Company company = companyMapper.selectByDto(companyDto);
		cleanCompanyByCompanyId(company.getId());
	}
	
	/**
	 * 根据当前人员，清除公司所有人员和角色的机构权限
	 */
	@Override
	public void cleanCompanyCacheByPartner(Long partnerId){
		if(Objects.isNull(partnerId)){
			return;
		}
		PartnerInfo partnerInfo = partnerInfoService.selectById(partnerId);
		if(Objects.nonNull(partnerInfo)){
			cleanCompanyByCompanyId(partnerInfo.getHigherid());
        }
	}
	
	/**
	 * 根据总代公司ID，清除总代公司人员以及角色的机构权限
	 * @param higherId
	 */
	private void cleanCompanyByCompanyId(Long higherId){
		PartnerInfoDto partnerInfoDto = new PartnerInfoDto();
		partnerInfoDto.setHigherid(higherId);
		List<PartnerInfo> partnerInfoList = partnerInfoService.selectListByDto(partnerInfoDto);
    	List<String> deleteKeys = new ArrayList<>();
    	if(CollectionUtils.isNotEmpty(partnerInfoList)){
            for(PartnerInfo pInfo: partnerInfoList){
                String userOrgPermissionKey = RedisKeyConstant.Permission.DEV_USER_ORG_PERMISSION + pInfo.getId();
                deleteKeys.add(userOrgPermissionKey);
            }
        }
    	
    	ChannelRoleDto roleDto = new ChannelRoleDto();
    	roleDto.setMerchantId(higherId);
    	List<ChannelRole> channelRoleList = channelRoleMapper.selectListByDto(roleDto);
    	channelRoleList.stream().forEach(channelRole -> {
    		 String roleOrgPermissionKey = RedisKeyConstant.Permission.DEV_ROLE_ORG_PERMISSION + channelRole.getId();
             deleteKeys.add(roleOrgPermissionKey);
    	});
    	
    	RedisUtil.delete(deleteKeys);
	}
	

	@Async
    @Override
    public void initDeptPermissionCode(Long companyId) {
		log.info("DeptPermissionServiceImpl->initDeptPermissionCode -> companyId:{}", companyId);
		try {
			Thread.sleep(500L);
			setDeptPermissionCode(companyId, 0L, null);
		} catch (InterruptedException e) {
			log.error("DeptPermissionServiceImpl->initDeptPermissionCode: {}", e);
			log.error(e.getMessage(), e);
		}
    }

    public void setDeptPermissionCode(Long companyId, Long parentId, String permissionCode){
        DepartmentDto departmentDto = new DepartmentDto();
        if(companyId.compareTo(0L) != 0){
            departmentDto.setMerchantId(companyId);
        }
        departmentDto.setParentId(parentId);
        // 新增 selectAllListByDto,将已删除部门也添加上权限及层级
        // 在报表处理过程中,已删除的部门作为历史相关记录也要能获取到
        List<Department> topDeptList = departmentDao.selectAllListByDto(departmentDto);
        if(CollectionUtils.isEmpty(topDeptList)){
            return;
        }

        for(Department topDept: topDeptList){
            String newPermissionCode = StringUtils.defaultIfBlank(permissionCode, "") + topDept.getId() + "-" ;
            departmentDto = new DepartmentDto();
            BeanUtils.copyProperties(topDept, departmentDto);
            departmentDto.setId(topDept.getId());
            if(topDept.getParentId().equals(0L)){
                newPermissionCode = topDept.getId() + "-";
            }
            departmentDto.setPermissionCode(newPermissionCode);
            // 部门层级: 顶级部门为机构名称,给予0级
            // 后续部门从1级开始.与Saas保持一致.因为saas的顶级部门不是公司名称
            departmentDto.setLayer(newPermissionCode.split("-").length - 1);
            departmentDao.saveOrUpdate(departmentDto);
            // 通过递归计算权限Code
            setDeptPermissionCode(companyId, topDept.getId(), newPermissionCode);
        }
    }

    @Override
    public AgencyPartnerPermission getAgencyPartnerPermission(Long partnerId) {
        AgencyPartnerPermission app = new AgencyPartnerPermission();
        PartnerInfo pi = partnerInfoService.selectById(partnerId);
        if(Objects.nonNull(pi) && MechanismAccountTypeEnum.mechanism.getNo().equals(pi.getAccountType())){
            app.setDeptPermission(DeptPermissionEnum.ALL.getNo());
            app.setPermissionIds(Arrays.asList(pi.getHigherid()));
            return app;
        }
        if(Objects.isNull(pi) || Objects.isNull(pi.getUserRoleId())){
            app.setDeptPermission(DeptPermissionEnum.MYSELF.getNo());
            app.setPermissionIds(Arrays.asList(partnerId));
            return app;
        }
        DeptPermissionDto dpDto = new DeptPermissionDto();
        dpDto.setBelongs(BelongsEnum.ROLE.getNo());
        dpDto.setBelongsId(pi.getUserRoleId());
        dpDto.setCompanyId(pi.getHigherid());
        DeptPermission dp = deptPermissionDao.selectByDto(dpDto);
        if(Objects.isNull(dp) || DeptPermissionEnum.MYSELF.getNo().equals(dp.getDeptPermission())){
            app.setDeptPermission(DeptPermissionEnum.MYSELF.getNo());
            app.setPermissionIds(Arrays.asList(partnerId));
        }else if(DeptPermissionEnum.ALL.getNo().equals(dp.getDeptPermission())){
            app.setDeptPermission(DeptPermissionEnum.ALL.getNo());
            app.setPermissionIds(Arrays.asList(pi.getHigherid()));
        }else if(DeptPermissionEnum.DEPT.getNo().equals(dp.getDeptPermission())){
            Long deptId = pi.getDeptId();
            Department department = departmentDao.selectById(deptId);
            if(Objects.isNull(department)){
                app.setDeptPermission(DeptPermissionEnum.MYSELF.getNo());
                app.setPermissionIds(Arrays.asList(partnerId));
                return app;
            }else {
                DepartmentDto deptDto = new DepartmentDto();
                deptDto.setPermissionCode(department.getPermissionCode());
                List<Department> departmentList = departmentDao.selectListByDto(deptDto);
                List<Long> deptIds = departmentList.stream()
                        .map(Department::getId).collect(Collectors.toList());
                if(CollectionUtils.isEmpty(deptIds)){
                    // 若部门删导致无部门时,直接已个人权限获取数据
                    app.setDeptPermission(DeptPermissionEnum.MYSELF.getNo());
                    app.setPermissionIds(Arrays.asList(partnerId));
                    return app;
                }
                app.setDeptPermission(DeptPermissionEnum.DEPT.getNo());
                app.setPermissionIds(deptIds);
            }
        }
        return app;
    }
}
